#pragma once

#include <iostream>
#include <string>
#include <vector>

using std::cerr;
using std::cout;
using std::endl;
using std::string;
using std::vector;

#define SEP 'x'
#define SEP_LEN sizeof(SEP)

void DelRelf(string *buffer)
{
    int pos = buffer->find('\n');
    if (pos == string::npos)
        return;
    else
        buffer->erase(pos);
}

// 分割每段报文 -- 提取完整的一个报文 -- TCP连续发送
void PackageSplit(string &inbuffer, vector<string> *result)
{
    while (true)
    {
        // "xxxxxx\3yyyyyyy\3zzzzzz\3abcdef" -> (*result) = {xxxxxx, yyyyyy, zzzzzzz}; inbuffer = "abcdef"
        size_t pos = inbuffer.find(SEP);
        if (pos == std::string::npos)
        {
            break;
        }
        else
        {
            result->emplace_back(inbuffer.substr(0, pos)); // 切割
            inbuffer.erase(0, pos + SEP_LEN);              // 擦除切割后的子串 -- 包含分割符
        }
    }
    DelRelf(&inbuffer);
}

//===========================================================================================

#define SPACE ' '
#define SPACELEN sizeof(SPACE)

// 定制协议 -- web calculator
struct Protocol
{
    class Requst
    {
    public:
        void Serialize(string *out) // 序列化 -- 结构化数据 -> 字符串
        {
            // "LeftOprand_ op_ RightOprand_"
            *out = std::to_string(LeftOperand_);
            *out += SPACE;
            *out += Operator_;
            *out += SPACE;
            *out += std::to_string(RightOperand_);
        }

        bool Deserialize(const string &in) // 反序列化 -- 字符串->结构化数据
        {
            // "LeftOprand_ op_ RightOprand_"
            int SpaceOne = in.find(SPACE);
            if (SpaceOne == string::npos)
                return false;

            int SpaceTwo = in.rfind(SPACE);
            if (SpaceTwo == string::npos)
                return false;

            LeftOperand_ = std::stoi(in.substr(0, SpaceOne));
            string Operator = in.substr(SpaceOne + SPACELEN, SpaceTwo - (SpaceOne + SPACELEN));
            if (Operator.size() != 1)
                return false;
            Operator_ = Operator[0];

            RightOperand_ = std::stoi(in.substr(SpaceTwo + SPACELEN));

            return true;
        }

    public:
        int GetLfetOperand() const { return LeftOperand_; }
        char GetOperator() const { return Operator_; }
        int GetRightOperand() const { return RightOperand_; }

        int &GetLfetOperand() { return LeftOperand_; }
        char &GetOperator() { return Operator_; }
        int &GetRightOperand() { return RightOperand_; }

    private:
        int LeftOperand_;
        char Operator_;
        int RightOperand_;
    };

    class Reponse
    {
    public:
        void Serialize(string *out) // 序列化 -- 结构化数据 -> 字符串
        {
            // "errorcode_ result_" -> "0 100"
            *out = std::to_string(errorcode_);
            *out += SPACE;
            *out += std::to_string(result_);
        }

        bool Deserialize(const string &in) // 反序列化 -- 字符串->结构化数据
        {
            // "errorcode_ result_" -> "0 100"
            int SpaceIndex = in.find(SPACE);
            if (SpaceIndex == string::npos)
                return false;

            errorcode_ = std::stoi(in.substr(0, SpaceIndex));
            result_ = std::stoi(in.substr(SpaceIndex + SPACELEN));

            return true;
        }

    public:
        int Geterrorcode() const { return errorcode_; }
        int Getresult() const { return result_; }

        int &Geterrorcode() { return errorcode_; }
        int &Getresult() { return result_; }

    private:
        int errorcode_ = 0; // 错误码 -- !0为计算异常 -- -2为非法运算符 -1为非法运算
        int result_;        // 计算结果
    };
};